package cn.yx.common.core.util.json.jackson;

import cn.yx.common.core.constant.message.JsonUtilMessageKey;
import cn.yx.common.core.exception.CommonException;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;

import java.util.List;
import java.util.Map;

/**
 * <p>封装Jackson的JsonUtil工具类</p>
 *
 * @author Wgssmart
 */
public final class JsonUtil {

    private JsonUtil() {
    }

    /**
     * 获取ObjectMapper对象
     *
     * @return
     */
    public static ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return objectMapper;
    }

    /**
     * Java对象转JSON字符串，不序列化null值
     *
     * @param value
     * @return
     */
    public static String toJsonStr(Object value) {
        return toJsonStr(value, true);
    }

    /**
     * Java对象转JSON字符串，可指定是否序列化null值
     *
     * @param value
     * @param nonNull
     * @return
     */
    public static String toJsonStr(Object value, boolean nonNull) {
        ObjectMapper objectMapper = new ObjectMapper();
        if (nonNull) {
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        }
        try {
            return objectMapper.writeValueAsString(value);
        } catch (JsonProcessingException e) {
            // @SimplifiedChinese=JSON解析异常
            // @English=JSON processing error
            throw new CommonException(JsonUtilMessageKey.JSON_PROCESSING_ERROR, e);
        }
    }

    /**
     * Java对象转格式化的JSON字符串，不序列化null值
     *
     * @param value
     * @return
     */
    public static String toPrettyJsonStr(Object value) {
        return toPrettyJsonStr(value, true);
    }

    /**
     * Java对象转格式化的JSON字符串，可指定是否序列化null值
     *
     * @param value
     * @param nonNull
     * @return
     */
    public static String toPrettyJsonStr(Object value, boolean nonNull) {
        ObjectMapper objectMapper = new ObjectMapper();
        if (nonNull) {
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        }
        try {
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(value);
        } catch (JsonProcessingException e) {
            throw new CommonException(JsonUtilMessageKey.JSON_PROCESSING_ERROR, e);
        }
    }

    /**
     * JSON字符串转Java对象
     *
     * @param jsonStr    JSON字符串
     * @param valueClass Java类
     * @param <T>
     * @return
     */
    public static <T> T toBean(String jsonStr, Class<T> valueClass) {
        try {
            return new ObjectMapper().readValue(jsonStr, valueClass);
        } catch (JsonProcessingException e) {
            throw new CommonException(JsonUtilMessageKey.JSON_PROCESSING_ERROR, e);
        }
    }

    /**
     * JSON字符串转Java对象列表
     *
     * @param jsonStr
     * @param valueClass
     * @param <T>
     * @return
     */
    public static <T> List<T> toBeanList(String jsonStr, Class<T> valueClass) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, valueClass);
            return new ObjectMapper().readValue(jsonStr, javaType);
        } catch (JsonProcessingException e) {
            throw new CommonException(JsonUtilMessageKey.JSON_PROCESSING_ERROR, e);
        }
    }

    /**
     * JSON字符串转Java对象Map
     *
     * @param jsonStr
     * @param keyClass
     * @param valueClass
     * @param <K>
     * @param <T>
     * @return
     */
    public static <K, T> Map<K, T> toBeanMap(String jsonStr, Class<K> keyClass, Class<T> valueClass) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(Map.class, keyClass, valueClass);
            return new ObjectMapper().readValue(jsonStr, javaType);
        } catch (JsonProcessingException e) {
            throw new CommonException(JsonUtilMessageKey.JSON_PROCESSING_ERROR, e);
        }
    }

}
